package com.googlecode.dgwt.client.dijit;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.googlecode.dgwt.client.dijit.resource.message.MessageResources;
import com.googlecode.dgwt.client.dijit.resource.template.TemplateResources;
import com.googlecode.dgwt.client.dijit.theme.Theme;
import com.googlecode.dgwt.client.dijit.theme.impl.StyleSheetInjectionEngine;
import com.googlecode.dgwt.client.dojo.NodeList;
import com.googlecode.dgwt.client.dojo.util.JsUtil;


/**
 * @author	Wellington Tadeu dos Santos
 * @since	DGWT v0.01
 */
public class Dijit implements EntryPoint {
    
    public static final String BASE_CLASSNAME = "dijit";
    public static final MessageResources MESSAGE_RESOURCES = GWT.create(MessageResources.class);
    public static final TemplateResources TEMPLATE_RESOURCES = GWT.create(TemplateResources.class);

    private static Theme theme;
    private static boolean loaded = false;
    static List<Widget> widgetList = new ArrayList<Widget>();

    
    /**
     * Initialization
     */
    @Override
    public void onModuleLoad() {
        if (!loaded){
            loaded = true; 

            StyleSheetInjectionEngine.get().sniff();
            getTheme().onLoad();
            
            DeferredCommand.addCommand(new Command() {
                public void execute() {
                    
                    for (Widget widget : widgetList){
                        widget.startup();
                    }
                }
            });
        }
    }
    
    
    /**
     * Define a new Theme for Dijit Widgets
     * @param newTheme
     */
    public static void setTheme(Theme newTheme) {
        
        assert (newTheme != null) : "Theme can't be NULL";        
        boolean reload = loaded && !newTheme.equals(theme);
        
        if (reload) {
            for (Widget widget : widgetList){
                widget.onThemeChanging(newTheme);
            }
            
            theme.onUnload();
        }
        
        Theme oldTheme = theme;
        theme = newTheme;
        
        if (reload) {
            StyleSheetInjectionEngine.get().updateDirection();
            theme.onLoad();

            for (Widget widget : widgetList){
                widget.onThemeChanged(oldTheme);
            }            
        }
    }

    
    /**
     * Gets the current Theme assigned to Dijit Widgets
     * @return
     */
    public static Theme getTheme() {
        if (theme == null){
            theme = Theme.getDefaultTheme();
        }
        return theme;
    }

    
    /**
     * Returns True this module is already loaded.
     * @return boolean
     */
    public static boolean isLoaded() {
        return loaded;
    }


    /**
     * 
     * @param node
     * @return
     */
    public static Widget byNode(Node node) {
        for (Widget widget : widgetList){
            if (JsUtil.absEquals(widget.getElement(), node)){
                return widget;
            }
        }
        return null;
    }

    
    /**
     * 
     * @param nodeList
     * @return
     */
    public static List<Widget> byNode(List<Node> nodeList) {
        List<Widget> widgets = new ArrayList<Widget>(nodeList.size());
        
        for (Node node : nodeList){
            Widget widget = Dijit.byNode(node);
            if (widget != null){
                widgets.add(widget);
            }
        }
        
        return widgets;
    }	
    
    
    public static NodeList<Element> query(com.google.gwt.user.client.ui.Widget ...widgets){
        NodeList<Element> nodeList = new NodeList<Element>(widgets.length);
        for (com.google.gwt.user.client.ui.Widget widget : widgets){
            nodeList.add(widget.getElement());
        }
        return nodeList;
    }
    
    
    public static NodeList<Element> query(String attachedElement, Widget ...widgets){
        NodeList<Element> nodeList = new NodeList<Element>(widgets.length);
        for (Widget widget : widgets){
            Element node = widget.getAttachedElement(attachedElement);
            
            assert (node != null) : 
                "Attachment not found: \"" + attachedElement + "\".\n" +
                "Try \"containerElement\", \"styleElement\", \"sizeableElement\", \"domElement\", etc..";
                
            nodeList.add(node);
        }
        return nodeList;
    }

    /**
     * 
     * Sets a state on an element. <br/>
     *<br/>
     * On Firefox 2 and below, we set an attribute in namespace
     * "http://www.w3.org/2005/07/aaa" with a name of the given state. On all
     * other browsers, we set an attribute called "aria-"+state.
     * 
     */
    public static native void setWaiState(Element elem, String state, String value) /*-{
        // TODO : tirar de native
        if(dojo.isFF < 3){
                elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
                        "aaa:"+state, value);
        }else{
                elem.setAttribute("aria-"+state, value);
        }
    }-*/;

    /**
     * Sets the role on an element.<br/>
     * <br/>
     * In other than FF2 replace existing role attribute with new role. FF3
     * supports XHTML and ARIA roles so if elem already has an XHTML role,
     * append this role to XHTML role and remove other ARIA roles. On Firefox 2
     * and below, "wairole:" is prepended to the provided role value.
     * 
     */
    public static native void setWaiRole(Element elem, String role) /*-{
        // TODO : tirar de native
        var _XhtmlRoles = /banner|contentinfo|definition|main|navigation|search|note|secondary|seealso/;
        var curRole = dojo.attr(elem, "role") || "";
        if(dojo.isFF < 3 || !_XhtmlRoles.test(curRole)){
                dojo.attr(elem, "role", dojo.isFF < 3 ? "wairole:" + role : role);
        }else{
                if((" "+ curRole +" ").indexOf(" " + role + " ") < 0){
                        var clearXhtml = dojo.trim(curRole.replace(_XhtmlRoles, ""));
                        var cleanRole = dojo.trim(curRole.replace(clearXhtml, ""));      
                dojo.attr(elem, "role", cleanRole + (cleanRole ? " " : "") + role);
                }
        }
    }-*/;

}
